home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / doom / suckmods.zip / SUCKMODS.ZIP / suck05 / src / combat.qc < prev    next >
Text File  |  1997-05-13  |  16KB  |  690 lines

  1. void() T_MissileTouch;
  2. void() info_player_start;
  3. void(entity targ, entity attacker) ClientObituary;
  4.  
  5.  
  6. //============================================================================
  7.  
  8. /*
  9. ============
  10. CanDamage
  11.  
  12. Returns true if the inflictor can directly damage the target.  Used for
  13. explosions and melee attacks.
  14. ============
  15. */
  16. float(entity targ, entity inflictor) CanDamage =
  17. {
  18. // bmodels need special checking because their origin is 0,0,0
  19.     if (targ.movetype == MOVETYPE_PUSH)
  20.     {
  21.         traceline(inflictor.origin, 0.5 * (targ.absmin + targ.absmax), TRUE, self);
  22.         if (trace_fraction == 1)
  23.             return TRUE;
  24.         if (trace_ent == targ)
  25.             return TRUE;
  26.         return FALSE;
  27.     }
  28.     
  29.     traceline(inflictor.origin, targ.origin, TRUE, self);
  30.     if (trace_fraction == 1)
  31.         return TRUE;
  32.     traceline(inflictor.origin, targ.origin + '15 15 0', TRUE, self);
  33.     if (trace_fraction == 1)
  34.         return TRUE;
  35.     traceline(inflictor.origin, targ.origin + '-15 -15 0', TRUE, self);
  36.     if (trace_fraction == 1)
  37.         return TRUE;
  38.     traceline(inflictor.origin, targ.origin + '-15 15 0', TRUE, self);
  39.     if (trace_fraction == 1)
  40.         return TRUE;
  41.     traceline(inflictor.origin, targ.origin + '15 -15 0', TRUE, self);
  42.     if (trace_fraction == 1)
  43.         return TRUE;
  44.  
  45.     return FALSE;
  46. };
  47.  
  48.  
  49. /*
  50. ============
  51. Killed
  52. ============
  53. */
  54. void(entity targ, entity attacker) Killed =
  55. {
  56.     local entity oself, tempe, onew, oother;
  57.  
  58.     oself = self;
  59.     self = targ;
  60.     
  61.     if (self.health < -99)
  62.         self.health = -99;        // don't let sbar look bad if a player
  63.  
  64.     if (self.movetype == MOVETYPE_PUSH || self.movetype == MOVETYPE_NONE)
  65.     {    // doors, triggers, etc
  66.  
  67.         self.th_die ();
  68.         self = oself;
  69.         return;
  70.     }
  71.  
  72.     if ((targ.health > -40) && (targ.rune_num == ITEM_RUNE_ANKH) && (random() < 0.9))
  73.     {
  74.         targ.msg_center = 1;
  75.         clientmsg(targ, "The power of the Ankh has resurrected you!\n");
  76.         targ.health = targ.health + 40;
  77.         self=oself;
  78.         return;
  79.     }
  80.  
  81.  
  82.     if ((attacker.rune_num == ITEM_RUNE_SARGON) &&
  83.         (targ.team == targ.lastteam))
  84.     {
  85.         tempe=spawn();
  86.         tempe.ammo_rockets=self.ammo_rockets;
  87.         tempe.ammo_shells=self.ammo_shells;
  88.         tempe.ammo_nails=self.ammo_nails;
  89.         tempe.ammo_cells=self.ammo_cells;
  90.         tempe.items=self.items;
  91.         tempe.owner = targ;
  92.         tempe.items = 0;
  93.         onew=self;
  94.         oother = other;
  95.         self=tempe;
  96.         other=attacker;
  97.         BackpackTouch();
  98.         other=oother;
  99.         self=onew;
  100.         self.ammo_rockets=0;
  101.         self.ammo_shells=0;
  102.         self.ammo_nails=0;
  103.         self.ammo_cells=0;
  104.         self.items=0;    
  105.     }
  106.  
  107.  
  108.     self.enemy = attacker;
  109.  
  110.     ClientObituary(self, attacker);
  111.     
  112.     self.takedamage = DAMAGE_NO;
  113.     self.touch = SUB_Null;
  114.  
  115.     self.th_die ();
  116.     
  117.     self = oself;
  118. };
  119.  
  120.  
  121. // *TEAMPLAY*
  122. // Prototypes
  123.  
  124. float(entity targ, entity inflictor, entity attacker, float damage) TeamArmorDam;
  125. float(entity targ, entity inflictor, entity attacker, float damage) TeamHealthDam;
  126.  
  127. /*
  128. ============
  129. T_Damage
  130.  
  131. The damage is coming from inflictor, but get mad at attacker
  132. This should be the only function that ever reduces health.
  133. ============
  134. */
  135. void(entity targ, entity inflictor, entity attacker, float damage) T_Damage=
  136. {
  137.     local    vector    dir;
  138.     local    entity    oldself;
  139.     local    float    save;
  140.     local    float    take;
  141.     local     string    tmp_string;
  142.     local     float    tmp_float, tmp2;
  143.     local     entity    e;
  144.     local   float  attacker_tmts, targ_tmts, modifier;
  145.         
  146.  
  147.     if (!targ.takedamage)
  148.         return;
  149.  
  150.     if ((targ.rune_num == ITEM_RUNE_LOKI) && (targ.loki_possessed) &&
  151.         (!(targ.player_flag&ITEM_ENEMY_FLAG)))
  152.         return;
  153.  
  154.     if (targ.stone_time > time)
  155.         return;
  156.  
  157.     //SUCK: Figure the momentum change first
  158.     if ( (inflictor != world) && (targ.movetype == MOVETYPE_WALK) &&
  159.         (targ.rune_num != ITEM_RUNE_MONK))
  160.     {
  161.         dir = targ.origin - (inflictor.absmin + inflictor.absmax) * 0.5;
  162.         dir = normalize(dir);
  163.         if ((attacker.rune_num == ITEM_RUNE_SAMURAI) &&
  164.             ((attacker.weapon == IT_ROCKET_LAUNCHER) ||
  165.             (attacker.weapon == IT_GRENADE_LAUNCHER)))
  166.             targ.velocity = targ.velocity  + dir * damage * 32;
  167.         else
  168.             targ.velocity = targ.velocity + dir*damage*8;
  169.     }
  170.  
  171.     // Ifrite does no damage to himself.
  172.     if ((attacker == targ) && (attacker.rune_num == ITEM_RUNE_IFRITE))
  173.         return;
  174.  
  175.     // Mars does less damage to himself...
  176.     if ((targ == attacker) && (attacker.rune_num == ITEM_RUNE_MARS))
  177.         damage = damage / 5;
  178.  
  179.     if (attacker.rune_num == ITEM_RUNE_MARS)
  180.         damage=damage*3;
  181.  
  182.     // Golom takes 1/4 damage..
  183.     if (targ.rune_num == ITEM_RUNE_GOLOM)
  184.         damage = damage / 4;
  185.  
  186.  
  187.     // Kizi does more damage the lower his health.
  188.     if (attacker.rune_num == ITEM_RUNE_KIZI)
  189.     {
  190.         if (attacker.health <= 40)
  191.             damage = damage * 3;
  192.         else if (attacker.health < 70)
  193.             damage = damage * 2;
  194.         else if (attacker.health < 85)
  195.             damage = damage * 1.5;
  196.     }
  197.  
  198.     // Kizi takes less damage the lower his health.
  199.     if (targ.rune_num == ITEM_RUNE_KIZI)
  200.     {
  201.         if (targ.health <= 40)
  202.             damage = damage / 3;
  203.         else if (attacker.health < 70)
  204.             damage = damage / 2;
  205.         else if (attacker.health < 85)
  206.             damage = damage / 1.5;
  207.     }
  208.  
  209.     // Sargon does double damage to the judaic set
  210.     if ((attacker.rune_num == ITEM_RUNE_SARGON) &&
  211.         ((targ.rune_num == ITEM_RUNE_GOLOM) ||
  212.         (targ.rune_num == ITEM_RUNE_SHYLOCK) ||
  213.         (targ.rune_num == ITEM_RUNE_SAMPSON) ||
  214.         (targ.rune_num == ITEM_RUNE_DAVID)))
  215.         damage = damage * 2;
  216.  
  217.     // Sargon does extra damage to the flag carrier.
  218.     else if ((attacker.rune_num == ITEM_RUNE_SARGON) &&
  219.         (targ.player_flag&ITEM_ENEMY_FLAG))
  220.         damage = damage * 2;
  221.  
  222.     // Mars takes 1.8x damage.
  223.     if (targ.rune_num == ITEM_RUNE_MARS)
  224.         damage=damage*1.8;
  225.  
  226.     if ((attacker.rune_num == ITEM_RUNE_WITCH) &&
  227.         (targ.classname == "player") &&
  228.         (targ.curse_time == 0) && (random() < 0.8) &&
  229.         (targ.team != attacker.team))
  230.     {
  231.         targ.msg_center = 1;
  232.         clientmsg(targ, "You have been cursed!\n");
  233.         targ.curse_time = time + 7;
  234.     }
  235.  
  236.     if ((targ.rune_num == ITEM_RUNE_MONK) && (vlen(targ.velocity) < 30) && ((targ.player_flag&ITEM_ENEMY_FLAG) == 0)
  237.         && ((targ.attack_finished + 3) < time))
  238.         return;
  239.  
  240.     // The vampire gains some of the health he takes from enemies.
  241.     if ((attacker.rune_num == ITEM_RUNE_VAMPIRE) &&
  242.         (attacker.team != targ.team) &&
  243.         (targ.classname == "player"))
  244.     {
  245.         if (attacker.health<170)
  246.         {
  247.             tmp_float = damage/3;
  248.             attacker.health=attacker.health + tmp_float;
  249.             if (attacker.health>200)
  250.                 attacker.health = 200;
  251.         }
  252.     }
  253.  
  254.     /* If Ytr is nearby and on the enemy team and we are the attacker,
  255.     decrease our strength. */
  256.     e=findradius(attacker.origin, 600);
  257.     while (e)
  258.     {
  259.         if ((e.rune_num == ITEM_RUNE_YTR) &&
  260.         (e.team != attacker.team))
  261.             damage = damage / 2;
  262.         e=e.chain;
  263.     }
  264.  
  265.     // Wendigo locks in the velocity of the enemy.
  266.     if ((attacker.rune_num == ITEM_RUNE_WENDIGO) && (targ!=attacker)
  267.     && (targ.team != attacker.team))
  268.     {
  269.         targ.lock_velocity=targ.velocity;
  270.         targ.lock_time=time+1.5;
  271.     }
  272.  
  273. // used by buttons and triggers to set activator for target firing
  274.     damage_attacker = attacker;
  275.  
  276.     //SUCK: Increase damage of attacker by 10% for every teammate close to him
  277.     //  and increase resistance of target by 10% for every teammate close to him.
  278.     if (teamplay&TEAM_GROUP_POWER)
  279.     {
  280.         attacker_tmts=0;
  281.         e=findradius(attacker.origin, 300);
  282.         while (e)
  283.         {
  284.             if (e.classname == "player")
  285.             {
  286.                 if (e.team == attacker.team)
  287.                     attacker_tmts=attacker_tmts + 1;
  288.             }
  289.             e=e.chain;
  290.         }
  291.         tmp_string=ftos(attacker_tmts);
  292.         targ_tmts=0;
  293.         e=findradius(targ.origin, 300);
  294.         while (e)
  295.         {
  296.             if (e.classname == "player")
  297.             {
  298.                 if (e.team == targ.team)
  299.                     targ_tmts=targ_tmts + 1;
  300.             }
  301.             e=e.chain;
  302.         }
  303.         tmp_string=ftos(targ_tmts);
  304.         while(attacker_tmts>0)
  305.         {
  306.             damage=damage*1.1;
  307.             attacker_tmts=attacker_tmts - 1;
  308.         }
  309.         while (targ_tmts>0)
  310.         {
  311.             damage=damage*0.9;
  312.             targ_tmts=targ_tmts - 1;
  313.         }
  314.     }
  315.  
  316.     // SUCK: If the player has the rune of castle, then his resistance and damage
  317.     // increase when he is near his flag
  318.     if (attacker.rune_num == ITEM_RUNE_CASTLE)
  319.     {
  320.         attacker_tmts=0;
  321.         e=findradius(attacker.origin, 800);
  322.         while (e)
  323.         {
  324.             if (((e.classname == "item_flag_team1") && (attacker.team == (TEAM_COLOR1 + 1))) ||
  325.                 ((e.classname == "item_flag_team2") && (attacker.team == (TEAM_COLOR2 + 1))))
  326.                 attacker_tmts=1;
  327.             e=e.chain;
  328.         }
  329.         if (attacker_tmts == 1)
  330.         {
  331.             if (attacker.super_sound< time)
  332.             {
  333.                 sound (attacker, CHAN_ITEM, "items/damage3.wav", 1, ATTN_NORM);
  334.                 attacker.super_sound = time + 1;
  335.             }
  336.             damage = damage * 3;
  337.         }
  338.         else
  339.             damage = damage    * 0.9;
  340.     }
  341.  
  342.     if (targ.rune_num == ITEM_RUNE_CASTLE)
  343.     {
  344.         targ_tmts = 0;
  345.         e=findradius(targ.origin, 800);
  346.         while (e)
  347.         {
  348.             if (((e.classname == "item_flag_team1") && (targ.team == (TEAM_COLOR1 + 1))) ||
  349.                 ((e.classname == "item_flag_team2") && (targ.team == (TEAM_COLOR2 + 1))))
  350.                 targ_tmts=1;
  351.             e=e.chain;
  352.         }
  353.         if (targ_tmts == 1)
  354.             damage = damage / 3;
  355.         else
  356.             damage = damage * 1.3;
  357.     }
  358.  
  359.     // SUCK: If he has the rune of siege, then he becomes more powerful
  360.     // near the ENEMY flag or if he has it.
  361.     if ((attacker.rune_num == ITEM_RUNE_SIEGE) &&
  362.         (attacker.player_flag&ITEM_ENEMY_FLAG))
  363.     {
  364.         damage = damage * 2;
  365.         if (attacker.super_sound< time)
  366.         {
  367.             sound (attacker, CHAN_ITEM, "items/damage3.wav", 1, ATTN_NORM);
  368.             attacker.super_sound = time + 1;
  369.         }
  370.     }
  371.     else if (attacker.rune_num == ITEM_RUNE_SIEGE)
  372.     {
  373.         attacker_tmts=0;
  374.         e=findradius(attacker.origin, 800);
  375.         while (e)
  376.         {
  377.             if (((e.classname == "item_flag_team1") && (attacker.team == (TEAM_COLOR2 + 1))) ||
  378.                 ((e.classname == "item_flag_team2") && (attacker.team == (TEAM_COLOR1 + 1))))
  379.                 attacker_tmts=1;
  380.             e=e.chain;
  381.         }
  382.         if (attacker_tmts == 1)
  383.         {
  384.             damage = damage * 2;
  385.  
  386.             if (attacker.super_sound< time)
  387.             {
  388.                 sound (attacker, CHAN_ITEM, "items/damage3.wav", 1, ATTN_NORM);
  389.                 attacker.super_sound = time + 1;
  390.             }
  391.         }
  392.     }
  393.     if ((targ.rune_num == ITEM_RUNE_SIEGE) &&
  394.         (targ.player_flag & ITEM_ENEMY_FLAG))
  395.     {
  396.         damage = damage / 2;
  397.         if (targ.invincible_sound < time) 
  398.         {
  399.         sound (targ, CHAN_ITEM, "items/protect3.wav", 1, ATTN_NORM);
  400.         targ.invincible_sound = time + 2;
  401.         }
  402.     }
  403.     else if (targ.rune_num == ITEM_RUNE_SIEGE)
  404.     {
  405.         targ_tmts=0;
  406.         e=findradius(targ.origin, 800);
  407.         while (e)
  408.         {
  409.             if (((e.classname == "item_flag_team1") && (targ.team == (TEAM_COLOR2 + 1))) ||
  410.                 ((e.classname == "item_flag_team2") && (targ.team == (TEAM_COLOR1 + 1))))
  411.                 targ_tmts=1;
  412.             e=e.chain;
  413.         }
  414.         if (targ_tmts == 1)
  415.         {
  416.             damage = damage / 2;
  417.             if (targ.invincible_sound < time) {
  418.                 sound (targ, CHAN_ITEM, "items/protect3.wav", 1, ATTN_NORM);
  419.                 targ.invincible_sound = time + 2;
  420.             }
  421.         }
  422.         else
  423.             damage = damage;
  424.     }
  425.  
  426.     // check for quad damage powerup on the attacker
  427.     if ((attacker.super_damage_finished > time) && 
  428.         (attacker.rune_num != ITEM_RUNE_MARS))
  429.         damage = damage * 4;
  430.  
  431.     // RUNE: check for double damage for rune of Black Magic powerup
  432.     if (attacker.rune_num == ITEM_RUNE_DBLDMG)
  433.         damage = damage * 2;
  434.  
  435.     if ((attacker.rune_num == ITEM_RUNE_VAMPIRE) ||
  436.         (attacker.rune_num == ITEM_RUNE_VIKING))
  437.         damage = damage * 1.3;
  438.  
  439.     if ((targ.rune_num == ITEM_RUNE_ARTHUR) &&
  440.         (attacker.classname == "player"))
  441.         damage = damage / 2;
  442.  
  443.     if ((targ.rune_num == ITEM_RUNE_VIKING) &&
  444.         (attacker.rune_num == ITEM_RUNE_ARTHUR))
  445.         damage = damage * 2.5;
  446.  
  447.     if ((attacker.rune_num == ITEM_RUNE_BALDER) &&
  448.         (targ.team != attacker.team))
  449.     {
  450.         targ.balder_slowdown = targ.balder_slowdown + 1;
  451.         targ.balder_time = time + 1;
  452.     }
  453.  
  454.     // The viking badly damages the priest
  455.     if ((attacker.rune_num == ITEM_RUNE_VIKING) &&
  456.         (targ.rune_num == ITEM_RUNE_PRIEST))
  457.         damage = damage * 2.5;
  458.  
  459.     // save damage based on the target's armor level
  460.  
  461.     // *TEAMPLAY*
  462.     // TeamArmorDam returns true iff the attacker can damage the target's
  463.     // armor
  464.     if (TeamArmorDam(targ, inflictor, attacker, damage))
  465.         save = ceil(targ.armortype*damage);
  466.     else
  467.         save = 0;
  468.  
  469.     // SUCK: The werewolf doesn't lose armor
  470.     if (targ.rune_num == ITEM_RUNE_WEREWOLF)
  471.         save=0;
  472.  
  473.     if (attacker.rune_num == ITEM_RUNE_SHOGUN)
  474.         save = save * 2;
  475.     
  476.  
  477.     if (save >= targ.armorvalue)
  478.     {
  479.         save = targ.armorvalue;
  480.         targ.armortype = 0;    // lost all armor
  481.         targ.items = targ.items - (targ.items & (IT_ARMOR1 | IT_ARMOR2 | IT_ARMOR3));
  482.     }
  483.  
  484.  
  485.     if (attacker.rune_num == ITEM_RUNE_SHOGUN)
  486.         save = save / 2;
  487.  
  488.     take = ceil(damage-save);
  489.  
  490.  
  491.     // Vulcan has tough skin.
  492.     if (targ.rune_num == ITEM_RUNE_VULCAN)
  493.         take = take / 2;
  494.  
  495.     //RUNE check if target has rune of Earth Magic (half damage)
  496.     if (targ.rune_num == ITEM_RUNE_RESIST) {
  497.         take = take / 2;
  498.         save = save / 2;
  499.         if (targ.invincible_sound < time) {
  500.             sound (targ, CHAN_ITEM, "items/protect3.wav", 1, ATTN_NORM);
  501.             targ.invincible_sound = time + 2;
  502.         }
  503.     }
  504.  
  505.     // Reduce his armor.
  506.     targ.armorvalue = targ.armorvalue - save;
  507.  
  508.     if ((targ.rune_num == ITEM_RUNE_SHYLOCK) &&
  509.         (targ != attacker) && (attacker.classname == "player"))
  510.     {
  511.         attacker.deathweapon="shylock";
  512.         T_Damage(attacker, targ, targ, damage);
  513.         attacker.deathweapon="";
  514.  
  515.     }
  516.  
  517.  
  518.     //SUCK: Vampires take 0.8x damage.
  519.     if (targ.rune_num == ITEM_RUNE_VAMPIRE) 
  520.     {
  521.         take = take * 0.8;
  522.         if (targ.rune_sound_start < time) 
  523.         {
  524.             sound(targ, CHAN_VOICE, "wizard/widle2.wav", 1, ATTN_NORM);
  525.             targ.rune_sound_start = time + 2.5;
  526.         }
  527.     }
  528.  
  529. // add to the damage total for clients, which will be sent as a single
  530. // message at the end of the frame
  531. // FIXME: remove after combining shotgun blasts?
  532.     if (targ.flags & FL_CLIENT)
  533.     {
  534.         targ.dmg_take = targ.dmg_take + take;
  535.         targ.dmg_save = targ.dmg_save + save;
  536.         targ.dmg_inflictor = inflictor;
  537.     }
  538.  
  539.     if (targ.invincible_finished >= time)
  540.     {
  541.         if (self.invincible_sound < time)
  542.         {
  543.             sound (targ, CHAN_ITEM, "items/protect3.wav", 1, ATTN_NORM);
  544.             self.invincible_sound = time + 2;
  545.         }
  546.         return;
  547.     }
  548.  
  549.     
  550.     // team play damage avoidance
  551.     if ( (teamplay == 1) && (targ.team > 0)&&(targ.team == attacker.team) )
  552.         return;
  553.  
  554. // *TEAMPLAY*
  555. // TeamHealthDam will return true if the attacker can damage the target's
  556. // health
  557.  
  558.             
  559. // do the damage
  560.     targ.health = targ.health - take;
  561.         if (!TeamHealthDam(targ, inflictor, attacker, damage))
  562.         targ.health = targ.health + take;
  563.         
  564.         if (!TeamHealthDam(targ, inflictor, attacker, damage))
  565.         return;
  566.  
  567.     if (targ.health <= 0)
  568.     {
  569.         Killed (targ, attacker);
  570.         return;
  571.     }
  572.  
  573.  
  574. // react to the damage
  575.     oldself = self;
  576.     self = targ;
  577.  
  578.     if (self.th_pain)
  579.     {
  580.         self.th_pain (attacker, take);
  581.     }
  582.  
  583.     self = oldself;
  584. };
  585.  
  586. /*
  587. ============
  588. T_RadiusDamage
  589. ============
  590. */
  591. void(entity inflictor, entity attacker, float damage, entity ignore) T_RadiusDamage =
  592. {
  593.     local    float     points;
  594.     local    entity    head;
  595.     local    vector    org;
  596.  
  597.     if (attacker.rune_num == ITEM_RUNE_IFRITE)
  598.         head = findradius(inflictor.origin, (damage+40)*1.4);
  599.     else
  600.         head = findradius(inflictor.origin, damage+40);
  601.     
  602.     while (head)
  603.     {
  604.         if (head != ignore)
  605.         {
  606.             if (head.takedamage)
  607.             {
  608.                 org = head.origin + (head.mins + head.maxs)*0.5;
  609.                 points = 0.5*vlen (inflictor.origin - org);
  610.                 if (points < 0)
  611.                     points = 0;
  612.                 points = damage - points;
  613.                 if (head == attacker)
  614.                     points = points * 0.5;
  615.                 if ((points > 0) && CanDamage(head, inflictor) &&
  616.                 ((head.rune_num != ITEM_RUNE_MONK) || (attacker == head)))
  617.                     T_Damage (head, inflictor, attacker, points);
  618.             }
  619.         }
  620.         head = head.chain;
  621.     }
  622. };
  623. /*
  624. ============
  625. T_DischargeDamage
  626. ============
  627. */
  628. void(entity inflictor, entity attacker, float damage, entity ignore) T_DischargeDamage =
  629. {
  630.     local    float     points;
  631.     local    entity    head;
  632.     local    vector    org;
  633.  
  634.     head = findradius(inflictor.origin, damage+40);
  635.     
  636.     while (head)
  637.     {
  638.         if (head != ignore)
  639.         {
  640.             if (head.takedamage)
  641.             {
  642.                 org = head.origin + (head.mins + head.maxs)*0.5;
  643.                 points = 0.5*vlen (inflictor.origin - org);
  644.                 if (points < 0)
  645.                     points = 0;
  646.                 points = damage - points;
  647.                 if (head == attacker)
  648.                     points = points * 0.5;
  649.                 if (points > 0)
  650.                 {
  651.                     if (CanDamage (head, inflictor))
  652.                         if (head.waterlevel > 1)
  653.                             T_Damage (head, inflictor, attacker, points);
  654.                 }
  655.             }
  656.         }
  657.         head = head.chain;
  658.     }
  659. };
  660.  
  661. /*
  662. ============
  663. T_BeamDamage
  664. ============
  665. */
  666. void(entity attacker, float damage) T_BeamDamage =
  667. {
  668.     local    float     points;
  669.     local    entity    head;
  670.     
  671.     head = findradius(attacker.origin, damage+40);
  672.     
  673.     while (head)
  674.     {
  675.         if (head.takedamage)
  676.         {
  677.             points = 0.5*vlen (attacker.origin - head.origin);
  678.             if (points < 0)
  679.                 points = 0;
  680.             points = damage - points;
  681.             if (head == attacker)
  682.                 points = points * 0.5;
  683.             if ((points > 0) && CanDamage(head, attacker))
  684.                 T_Damage (head, attacker, attacker, points);
  685.         }
  686.         head = head.chain;
  687.     }
  688. };
  689.  
  690.